#pragma once
#include<iostream>
#include<pthread.h>
#include<queue>
#include"Mutex.hpp"
#include"Cond.hpp"

namespace bpModule
{
    using namespace LockModule;
    using namespace CondModule;
    

    //version 2
    template<typename T>
    class BlockQueue
    {
    private:
        bool IsFull(){return _q.size() == _maxcap;}
        bool IsEmpty(){return _q.empty();}
    public:
        BlockQueue(int cap):_maxcap(cap),_cwaitnum(0),_pwaitnum(0)
        {
            //我们使用的是封装好的Cond 和Mutex 对应的构造函数会自动调用
        }
        void Equeue(const T& in)
        {
            LockGuard lockgard(_mutex);
            while(IsFull())    //防止伪唤醒,通常使用while
            {
                _pwaitnum++;
                _producer_cond.Wait(_mutex);
                _pwaitnum--;
            }
            //生产
            _q.push(in);
            if(_cwaitnum)
            {
                _consumer_cond.Notify();
            }
        }
        void Pop(T* out)
        {
            LockGuard lockgard(_mutex);
            while(IsEmpty())    //防止伪唤醒,通常使用while
            {
                _cwaitnum++;
                _consumer_cond.Wait(_mutex);
                _cwaitnum--;
            }
            //消费
            *out =_q.front();
            _q.pop();


            //叫醒对方
            if(_pwaitnum)
            {
                _producer_cond.Notify();
            }

        }

        ~BlockQueue()
        {
            //生命周期结束时,自动调用析构函数
        }

    private:
        std::queue<T> _q;               // 保存数据的容器，临界资源
        int  _maxcap;                   //bp最大容量
        Mutex _mutex;         //互斥
        Cond  _producer_cond; //生产者条件变量
        Cond  _consumer_cond; //消费者条件变量

        int _cwaitnum;
        int _pwaitnum;

    };


    //使用原生接口
    //version1
    // template<typename T>
    // class BlockQueue
    // {
    // private:
    //     bool IsFull(){return _q.size() == _maxcap;}
    //     bool IsEmpty(){return _q.empty();}
    // public:
    //     BlockQueue(int cap):_maxcap(cap),_cwaitnum(0),_pwaitnum(0)
    //     {
    //         pthread_mutex_init(&_mutex, nullptr);
    //         pthread_cond_init(&_producer_cond ,nullptr);
    //         pthread_cond_init(&_consumer_cond ,nullptr);

    //     }
    //     void Equeue(const T& in)
    //     {
    //         pthread_mutex_lock(&_mutex);
    //         while(IsFull())    //防止伪唤醒,通常使用while
    //         {
    //             _pwaitnum++;
    //             pthread_cond_wait(&_producer_cond,&_mutex);
    //             _pwaitnum--;
    //         }
    //         //生产
    //         _q.push(in);
    //         if(_cwaitnum)
    //         {
    //             pthread_cond_signal(&_consumer_cond);
    //         }
    //         pthread_mutex_unlock(&_mutex);

    //     }
    //     void Pop(T* out)
    //     {
    //         pthread_mutex_lock(&_mutex);
    //         while(IsEmpty())    //防止伪唤醒,通常使用while
    //         {
    //             _cwaitnum++;
    //             pthread_cond_wait(&_consumer_cond,&_mutex);
    //             _cwaitnum--;
    //         }
    //         //消费
    //         *out =_q.front();
    //         _q.pop();


    //         //叫醒对方
    //         if(_pwaitnum)
    //         {
    //             pthread_cond_signal(&_producer_cond);
    //         }
    //         pthread_mutex_unlock(&_mutex);
    //     }

    //     ~BlockQueue()
    //     {
    //         pthread_mutex_destroy(&_mutex);
    //         pthread_cond_destroy(&_producer_cond);
    //         pthread_cond_destroy(&_consumer_cond);
    //     }

    // private:
    //     std::queue<T> _q;               // 保存数据的容器，临界资源
    //     int  _maxcap;                   //bp最大容量
    //     pthread_mutex_t _mutex;         //互斥
    //     pthread_cond_t  _producer_cond; //生产者条件变量
    //     pthread_cond_t  _consumer_cond; //消费者条件变量

    //     int _cwaitnum;
    //     int _pwaitnum;

    // };

}